package com.zzb.projectfactory.framework.query;

import org.apache.commons.collections4.CollectionUtils;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

/**
 * 获取所有父级对象的field
 * Created by zhangzhenbin on 2016/12/13.
 */
public class ReflectionUtils {
    public static Field[] getAllDeclaredFields(Class clazz){
        return getThisClassDeclaredField(clazz,new ArrayList<>()).toArray(new Field[]{});
    }

    public static Field getAllDeclaredField(Class clazz, String fieldName){
        List<Field> thisClassDeclaredField = getThisClassDeclaredField(clazz,new ArrayList<>());
        return thisClassDeclaredField.stream().filter(field -> field.getName().equals(fieldName)).findFirst().orElse(null);
    }

    private static List<Field> getThisClassDeclaredField(Class clazz ,List<Field> list){
        if(clazz.getSuperclass().equals(Object.class)){
            Field[] declaredFields = clazz.getDeclaredFields();
            CollectionUtils.addAll(list,declaredFields);
            return list;
        }else {
            Field[] declaredFields = clazz.getDeclaredFields();
            CollectionUtils.addAll(list,declaredFields);
            return getThisClassDeclaredField(clazz.getSuperclass(),list);
        }
    }

    /**
     * 循环向上转型, 获取对象的 DeclaredMethod
     * @param object : 子类对象
     * @param methodName : 父类中的方法名
     * @param parameterTypes : 父类中的方法参数类型
     * @return 父类中的方法对象
     */

    public static Method getDeclaredMethod(Object object, String methodName, Class<?> ... parameterTypes){
        Method method = null ;
        Class<?> clazz;

        if(object instanceof Class ){
            clazz = (Class<?>) object;
        } else {
            clazz = object.getClass();
        }

        for(; clazz != Object.class ; clazz = clazz.getSuperclass()) {
            try {
                method = clazz.getDeclaredMethod(methodName, parameterTypes) ;
                return method ;
            } catch (Exception e) {
                //这里甚么都不要做！并且这里的异常必须这样写，不能抛出去。
                //如果这里的异常打印或者往外抛，则就不会执行clazz = clazz.getSuperclass(),最后就不会进入到父类中了

            }
        }
        return null;
    }
}
